package com.rwy.util;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.ReflectionUtils;

public class BeanUtils {
	
	private static void handleReflectionException(Exception e) {
		ReflectionUtils.handleReflectionException(e);
	}
	
	public static Object cloneBean(Object bean){
		try {
			return org.apache.commons.beanutils.BeanUtils.cloneBean(bean);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static <T, U> List<U> copyProperties(List<T> sourceList, Class<U> clazz) {
		
		if(sourceList == null || sourceList.size() <= 0) {
			return null;
		}
		
        List<U> result = new ArrayList<>();
        for (T source : sourceList) {
        	result.add(copyProperties(source, clazz));
    	}
        
        return result;
    }
	/**
	 * 如果source , 为空返回空对象
	 * @param sourceList
	 * @param clazz
	 * @return
	 */
    public static <T, U> List<U> copyPropertiesList(List<T> sourceList, Class<U> clazz) {
		
		if(sourceList == null || sourceList.size() <= 0) {
			return new ArrayList<U>();
		}
		
        List<U> result = new ArrayList<>();
        U target = null;
        for (T source : sourceList) {
    		try {
                target = clazz.newInstance();
                copyProperties(source, target);
    		}catch(Exception e) {
            	handleReflectionException(e);
    			return null;
    		}
            result.add(target);
    	}
        
        return result;
    }
	
	public static <T> T copyProperties(Object orig, Class<T> destClass) {
		
		if(orig == null) {
			return null;
		}
		
		try {
			Object target = destClass.newInstance();
			copyProperties(orig, (Object)target);
			return (T)target;
		}catch(Exception e) {
			handleReflectionException(e);
			return null;
		}
	}
	
	public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper beanWrapper = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] propDesc = beanWrapper.getPropertyDescriptors();

        Set<String> emptynames = new HashSet<String>();
        
        for(java.beans.PropertyDescriptor pd : propDesc) {
            Object srcValue = beanWrapper.getPropertyValue(pd.getName());
            if (srcValue == null) emptynames.add(pd.getName());
        }
        
        String[] result = new String[emptynames.size()];
        return emptynames.toArray(result);
    }
	
	public static void copyProperties(Object orig, Object dest) {
		try {
			org.apache.commons.beanutils.BeanUtils.copyProperties(dest, orig);
		} catch (Exception e) {
			handleReflectionException(e);
		}
	}

	public static void copyProperty(Object bean, String name, Object value) {
		try {
			org.apache.commons.beanutils.BeanUtils.copyProperty(bean, name, value);
		} catch (Exception e) {
			handleReflectionException(e);
		}
	}

	public static Map<String, String> describe(Object bean) {
		try {
			return org.apache.commons.beanutils.BeanUtils.describe(bean);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String[] getArrayProperty(Object bean, String name){
		try {
			return org.apache.commons.beanutils.BeanUtils.getArrayProperty(bean, name);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String getIndexedProperty(Object bean, String name, int index){
		try {
			return org.apache.commons.beanutils.BeanUtils.getIndexedProperty(bean, name, index);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String getIndexedProperty(Object bean, String name){
		try {
			return org.apache.commons.beanutils.BeanUtils.getIndexedProperty(bean, name);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String getMappedProperty(Object bean, String name, String key){
		try {
			return org.apache.commons.beanutils.BeanUtils.getMappedProperty(bean, name, key);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String getMappedProperty(Object bean, String name){
		try {
			return org.apache.commons.beanutils.BeanUtils.getMappedProperty(bean, name);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String getNestedProperty(Object bean, String name){
		try {
			return org.apache.commons.beanutils.BeanUtils.getNestedProperty(bean, name);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String getProperty(Object bean, String name){
		try {
			return org.apache.commons.beanutils.BeanUtils.getProperty(bean, name);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static String getSimpleProperty(Object bean, String name) {
		try {
			return org.apache.commons.beanutils.BeanUtils.getSimpleProperty(bean, name);
		} catch (Exception e) {
			handleReflectionException(e);
			return null;
		}
	}

	public static void populate(Object bean, Map properties) {
		try {
			org.apache.commons.beanutils.BeanUtils.populate(bean, properties);
		} catch (Exception e) {
			handleReflectionException(e);
		}
	}

	public static void setProperty(Object bean, String name, Object value) {
		try {
			org.apache.commons.beanutils.BeanUtils.setProperty(bean, name, value);
		} catch (Exception e) {
			handleReflectionException(e);
		}
	}

}